package yxy.cherry.battle.module.selector;

import yxy.cherry.battle.Fighter;
import yxy.cherry.battle.NiuBee;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.PropertyType;

import java.util.*;

/** 目标选择器 */
public abstract class TargetSelector implements Cloneable {

	/** 常规目标 */
	static protected Map<Position, LinkedList<Position>> TARGET_SEQUENCE = new HashMap<>();

	static {
		// 前上 -> 前上，前中，前下，后上，后中，后下
		TARGET_SEQUENCE.put(Position.FU, new LinkedList<Position>(Arrays.asList(Position.FU, Position.FM, Position.FD, Position.BU, Position.BM, Position.BD)));
		// 前中 -> 前中，前上，前下，后中，后上，后下
		TARGET_SEQUENCE.put(Position.FM, new LinkedList<Position>(Arrays.asList(Position.FM, Position.FU, Position.FD, Position.BM, Position.BU, Position.BD)));
		// 前下 -> 前下，前中，前上，后下，后中，后上
		TARGET_SEQUENCE.put(Position.FD, new LinkedList<Position>(Arrays.asList(Position.FD, Position.FM, Position.FU, Position.BD, Position.BM, Position.BU)));
		// 后上 -> 前上，前中，前下，后上，后中，后下
		TARGET_SEQUENCE.put(Position.BU, new LinkedList<Position>(Arrays.asList(Position.FU, Position.FM, Position.FD, Position.BU, Position.BM, Position.BD)));
		// 后中 -> 前中，前上，前下，后中，后上，后下
		TARGET_SEQUENCE.put(Position.BM, new LinkedList<Position>(Arrays.asList(Position.FM, Position.FU, Position.FD, Position.BM, Position.BU, Position.BD)));
		// 后下 -> 前下，前中，前上，后下，后中，后上
		TARGET_SEQUENCE.put(Position.BD, new LinkedList<Position>(Arrays.asList(Position.FD, Position.FM, Position.FU, Position.BD, Position.BM, Position.BU)));
	}

	private TeamSelector teamSelector;
	private int param1;
	private int param2;

	public void setTeamSelector(TeamSelector teamSelector) {
		this.teamSelector = teamSelector;
	}

	public void setParam(int param1, int param2) {
		this.param1 = param1;
		this.param2 = param2;
	}

	public Set<Fighter> selectTarget(Fighter actor) {
		Team team = null;
		if (teamSelector != null) {
			team = teamSelector.selectTeam(actor);
		}

		try {
			return target(actor, team, param1, param2);
		} catch (Exception e) {
			return null;
		}
	}

//    public abstract Set<Fighter> target(Fighter actor, Team team, int param);

    /**
	 * 根据参数获取指定的玩家集合
	 * @param actor
	 * @param team
	 * @param param1 参照技能表-目标
	 * @param param2 参照技能表-目标
	 * @return
	 */
	abstract public Set<Fighter> target(Fighter actor, Team team, int param1, int param2);

	protected Fighter get普通对手目标(Fighter actor) {
		Position actorPosition = actor.getPosition();
		if (actor instanceof NiuBee) {
			actorPosition = Position.FU;
		}
		LinkedList<Position> targetPositionList = TARGET_SEQUENCE.get(actorPosition);
		for (Position targetpoPosition : targetPositionList) {
			Fighter target = actor.getTeam().getTeam对手().getFighterByPosition(targetpoPosition);
			if (target == null) {
				continue;
			}
			if (target.is活着()) {
				return target;
			}
		}
		return null;
	}

	/**
	 * 根据排序获得指定数量的玩家并返回
	 * @param actor 施法者
	 * @param fighters
	 * @param sortType 0最低，1最高，2最低非自己，3最高非自己
	 * @param number
	 * @return
	 */
	protected  Set<Fighter> getSpecialFighter(Fighter actor,ArrayList<Fighter> fighters, int sortType, int number){
		if (sortType == 0) {//取最低
			if(fighters.size() > number) {
				return packTarget(fighters.subList(0, number));
			}else{
				return packTarget(fighters);
			}
		}else if(sortType == 1){//取最高
			if(fighters.size() > number){
				return packTarget(fighters.subList(fighters.size()-number,fighters.size()));
			}else{
				return packTarget(fighters);
			}
		}else if(sortType == 2){//最低非自己
			ArrayList<Fighter> fighters1 = new ArrayList<>();
			for(Fighter fighter:fighters){
				if(!fighter.equals(actor)){
					fighters1.add(fighter);
				}
			}
			if(fighters1.size() > number) {
				return packTarget(fighters1.subList(0, number));
			}else{
				return packTarget(fighters1);
			}
		}else{//最高非自己
			ArrayList<Fighter> fighters1 = new ArrayList<>();
			for(Fighter fighter:fighters){
				if(!fighter.equals(actor)){
					fighters1.add(fighter);
				}
			}
			if(fighters1.size() > number){
				return packTarget(fighters.subList(fighters1.size()-number,fighters1.size()));
			}else{
				return packTarget(fighters1);
			}
		}
	}

	/** 封装目标玩家 */
	protected Set<Fighter> packTarget(Fighter... targets) {
		HashSet<Fighter> set = new HashSet<Fighter>();
		for (Fighter target : targets) {
			set.add(target);
		}
		return set;
	}

	protected Set<Fighter> packTarget(List<Fighter> fighterList){
		HashSet<Fighter> set = new HashSet<Fighter>();
		for (Fighter target : fighterList) {
			set.add(target);
		}
		return set;
	}

	/** 封装目标玩家 */
	protected Set<Fighter> packTarget(Team team, Position... positions) {
		HashSet<Fighter> set = new HashSet<Fighter>();
		for (Position position : positions) {
			Fighter fighter = team.getFighterByPosition(position);
			if (fighter == null || !fighter.is活着()) {
				continue;
			}
			set.add(fighter);
		}
		return set;
	}

	/**
	 * 选择目标
	 * */
	protected Set<Fighter> randomTarget(Set<Fighter> set, int type, int num) {
		if (set == null || set.size() <= 0) {
			return null;
		}
		if (num == 0 || set.size() <= num) {
			return set;
		}
		ArrayList<Fighter> list = new ArrayList<>(set);
		Collections.shuffle(list);
		return new HashSet<>(list.subList(0, num));
	}

	/**
	 * 选择单个目标
	 */
	protected Set<Fighter> getFighterByPosition(Position position, Team team){
		Set<Fighter> set = packTarget(team,position);
		return set;
	}

	/** 获取某一行目标 */
	protected Set<Fighter> getRow(Position position, Team team) {
		switch (position) {
		case FM:
		case BM: {
			Set<Fighter> set = packTarget(team, Position.FM, Position.BM);
			if (set.size() == 0) {
				return null;
			}
			return set;
		}
		case FD:
		case BD: {
			Set<Fighter> set = packTarget(team, Position.FD, Position.BD);
			if (set.size() == 0) {
				return null;
			}
			return set;
		}
		case FU:
		case BU: {
			Set<Fighter> set = packTarget(team, Position.FU, Position.BU);
			if (set.size() == 0) {
				return null;
			}
			return set;
		}
		}
		return null;
	}

	/**
	 * 获取某一列目标
	 * @param position
	 * @param team
	 * @return
	 */
	protected Set<Fighter> getLine(Position position, Team team) {
		switch (position) {
			case FU:
			case FM:
			case FD:{
				Set<Fighter> set = packTarget(team, Position.FU, Position.FM, Position.FD);
				if(set.size() == 0){
					return null;
				}
				return set;
			}
			case BU:
			case BM:
			case BD:{
				Set<Fighter> set = packTarget(team, Position.BU, Position.BM, Position.BD);
				if(set.size() == 0){
					return null;
				}
				return set;
			}
		}
		return null;
	}

	/** 根据属性值排序 */
	protected ArrayList<Fighter> sortProperty(Team team, PropertyType propertyType) {
		ArrayList<Fighter> list = new ArrayList<Fighter>(team.get活人());
		list.sort(new Comparator<Fighter>() {

			@Override
			public int compare(Fighter o1, Fighter o2) {
				if (!o1.is活着()) {
					return -1;
				}
				if (o1.getProperty(propertyType) == o2.getProperty(propertyType)) {
					return o2.getPosition().getValue() - o1.getPosition().getValue();
				}
				return o1.getProperty(propertyType) > o2.getProperty(propertyType) ? 1 : -1;
			}
		});
		return list;
	}

	@Override
	protected TargetSelector clone() throws CloneNotSupportedException {
		return (TargetSelector) super.clone();
	}

	static public class TeamSelector {
		private int type;

		public TeamSelector(int type) {
			this.type = type;
		}

		public Team selectTeam(Fighter actor) {
			switch (type) {
			case 1:
			default:
				return actor.getTeam();
			case 2:
				return actor.getTeam().getTeam对手();
			}
		}
	}
}
